
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <AlignResult.h>

using namespace std;

void generateAlignResult(AlignResult* alignResult, const int numAlign, 
			const int readLength, const unsigned int refLength) {
	alignResult->_numAlign = numAlign;
	alignResult->_readLength = readLength;
	alignResult->_qscore = new unsigned char[readLength*numAlign];
	alignResult->_pos = new unsigned int[numAlign];
	alignResult->_hit = new int[numAlign];
	alignResult->_strand = new char[numAlign];
	alignResult->_offset = new uchar2[numAlign];
	alignResult->_sub = new char2[numAlign];

	for(int i = 0; i < numAlign; i++) {
		for(int j = 0; j < readLength; j++) {
			(alignResult->_qscore + i*readLength)[j] = rand()%9 + 1;
		}
		alignResult->_pos[i] = rand()%refLength;
		alignResult->_hit[i] = rand()%10;
		alignResult->_strand[i] = rand()%2;
		alignResult->_offset[i].x = rand()%readLength;
		alignResult->_offset[i].y = rand()%readLength;
		alignResult->_sub[i].x = rand()%4;
		alignResult->_sub[i].y = rand()%4;
	}
}

void rangePartition(AlignResult* out, AlignResult* in, unsigned int begin, unsigned int end) {
	char* label = new char[in->_numAlign];	
	memset(label, 0, sizeof(char)*in->_numAlign);
	for(unsigned int i = 0; i < in->_numAlign; i++) {
		if(in->_pos[i] >= begin && in->_pos[i] < end) {
			label[i] = 1;
		}
	}
	const unsigned int s = sum(label, in->_numAlign);
	out->_numAlign = s;

	cout << "begin = " << begin << ", end = " << end << endl;
	cout << "out->_numAlign = " << out->_numAlign << endl;

	out->_readLength = in->_readLength;
	const unsigned int readLength = out->_readLength;
	out->_qscore = new unsigned char[readLength*(out->_numAlign)];
	out->_pos = new unsigned int[out->_numAlign];
	out->_hit = new int[out->_numAlign];
	out->_strand = new char[out->_numAlign];
	out->_offset = new uchar2[out->_numAlign];
	out->_sub = new char2[out->_numAlign];

	

	unsigned int count = 0;
	unsigned char* qscore = NULL;
	for(unsigned int i = 0; i < in->_numAlign; i++) {
		if(label[i]) {
			qscore = in->get_qscore(i);
			memcpy(out->get_qscore(count), qscore, sizeof(char)*readLength);	
			out->_pos[count] = in->_pos[i];
			out->_hit[count] = in->_hit[i];
			out->_strand[count] = in->_strand[i];
			out->_offset[count] = in->_offset[i];
			out->_sub[count] = in->_sub[i];

			count += 1;
		}
	}
	assert(count == out->_numAlign);

	delete label;
}


void test_AlignResult() {

	const unsigned int readLength = 100;
	const unsigned int refLength = 1000000;
	const unsigned int winSize = 1000;
	const unsigned int bucketSize = 100;
	const unsigned int numAlign = 10000000;
	string fileName = "align.out";
	AlignResult* result = new AlignResult;
	generateAlignResult(result, numAlign, readLength, refLength);

	//write
	cout << "write ..................................." << endl;
	AlignResultWrite* write = new AlignResultWrite(readLength, refLength, 
						winSize, bucketSize, fileName);
	write->insert(result);
	write->close();	

	
	//read
	cout << endl << endl << "read ..................................." << endl;
	AlignResultRead* read = new AlignResultRead(fileName);
	AlignResult* gold = new AlignResult;
	AlignResult* out = new AlignResult;
	unsigned int begin, end;
	for(int winId = 0; winId < read->getNumBucket(); winId++) {
		read->fetchWindow(out, winId);
		//out->print();
		//printLine();
		cout << "fetchWindow done." << endl;
	
		begin = winId*winSize;
		end = (winId + 1)*winSize;
		rangePartition(gold, result, begin, end);	
		//gold->print();
		//printLine();	
		cout << "rangePartition done." << endl;

		if(gold->compare(out)) {
			cout << "Test pass :)" << endl;
		} else {
			cout << "TEST FAIL!!!!!!!!!" << endl;
			break;
		}
		

		out->close();
		gold->close();

		cout << "window " << winId << "/" << read->getNumBucket() << " done..." << endl << endl << endl;
	}


	delete read;
	delete write;
	delete gold;
	delete out;

}

